const fs = require("fs-extra");
const path = require("path");

const { createPluginContainer } = require("../server/pluginContainer");
const resolvePlugin = require("../plguins/resolve");
const { normalizePath } = require("../utils");

const htmlTypesRE = /\.html$/;
// 匹配 <script type="module" src="./src/main.js"></script>
const scriptModuleRE = /<script type="module" src="(.+?)"><\/script>/;
const JS_TYPES_RE = /\.js$/;

async function esBuildScanPlugin(config, depImports) {
  config.plugins = [resolvePlugin(config)];
  const container = await createPluginContainer(config);
  const resolve = async (
    importee,
    importer = path.join(config.root, "index.html")
  ) => {
    // 从 importer 中获取引入的包 importee
    return await container.resolveId(importee, importer);
  };
  return {
    name: "vite:dep-scan",
    setup(build) {
      build.onResolve({ filter: htmlTypesRE }, async ({ path, importer }) => {
        const resolved = await resolve(path, importer);

        if (resolved) {
          return {
            path: resolved.id || resolved,
            namespace: "html", // 将 html 文件存放到自定义命名空间下
          };
        }
      });

      build.onResolve({ filter: /.*/ }, async ({ path, importer }) => {
        const resolved = await resolve(path, importer);

        if (resolved) {
          const id = resolved.id || resolved;
          const included = id.includes("node_modules");
          if (included) {
            depImports[path] = normalizePath(id);
            return {
              path: id,
              external: true,
            };
          }
          return {
            path: id,
          };
        }
      });
      build.onLoad(
        { filter: htmlTypesRE, namespace: "html" },
        async ({ path }) => {
          // 读取 html 文件内容
          const html = fs.readFileSync(path, "utf-8");
          const [_, scriptSrc] = html.match(scriptModuleRE);
          const js = `import ${JSON.stringify(scriptSrc)}`;

          return {
            contents: js,
            loader: "js",
          };
        }
      );
      build.onLoad({ filter: JS_TYPES_RE }, async ({ path: p }) => {
        const ext = path.extname(p).slice(1);
        const contents = fs.readFileSync(p, "utf-8");
        return {
          contents, // import {createApp} from 'vue';
          loader: ext,
        };
      });
    },
  };
}

module.exports = esBuildScanPlugin;
